package com.ldgame.sound;

import java.io.InputStream;
import java.nio.IntBuffer;
import java.util.ArrayList;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.openal.AL;
import org.lwjgl.util.WaveData;
import org.newdawn.slick.util.ResourceLoader;

import static org.lwjgl.openal.AL10.*;

public class SoundSystem {
	private static ArrayList<IntBuffer> sources;
	private static ArrayList<IntBuffer> buffers;
	
	public static int init() {
		sources = new ArrayList<IntBuffer>();
		buffers = new ArrayList<IntBuffer>();
		
		try {
			AL.create();
		} catch (LWJGLException e) {
			e.printStackTrace();
		}
		
		if (alGetError() != AL_NO_ERROR) {
			return AL_FALSE;
		}
		
		addSound(ResourceLoader.getResourceAsStream("com/res/laser.wav"), false);
		addSound(ResourceLoader.getResourceAsStream("com/res/theme.wav"), true);
		
		return AL_TRUE;
	}
	
	public static int addSound(InputStream fileName, boolean loop) {
		IntBuffer buffer = BufferUtils.createIntBuffer(1);
		IntBuffer source = BufferUtils.createIntBuffer(1);
		buffers.add(buffer);
		sources.add(source);
		
		alGenSources(source);
		alGenBuffers(buffer);
		
		alSourcef(source.get(0), AL_GAIN, 0.2f);
		if (loop) {
			alSourcei(source.get(0), AL_LOOPING, AL_TRUE);
		}
		
		if(alGetError() != AL_NO_ERROR) {
			return AL_FALSE;
		}
		
		WaveData waveFile = WaveData.create(fileName);
		alBufferData(buffer.get(0), waveFile.format, waveFile.data, waveFile.samplerate);
		waveFile.dispose();
		
		alSourcei(source.get(0), AL_BUFFER, buffer.get(0));
		return AL_TRUE;
	}
	
	public static void playSound(Sound sound) {
		alSourcePlay(sources.get(sound.ordinal()).get(0));
	}
	
	public static void pauseSound() {
		for (IntBuffer source : sources) {
			alSourcePause(source.get(0));
			alSourceRewind(source.get(0));
		}
	}
	
	public static void setVolume(float volume) {
		for (IntBuffer source : sources) {
			alSourcef(source.get(0), AL_GAIN, volume);
		}
	}
	
	public static void destroy() {
		for (IntBuffer source : sources) {
			alDeleteSources(source);
		}
		
		for (IntBuffer buffer : buffers) {
			alDeleteBuffers(buffer);
		}
		
		AL.destroy();
	}
}
